﻿// ------------------------------------------------------------------------------------------------
//  <copyright file="Fragment.cs" company="Iveely">
//    Copyright (c) Iveely Liu.  All rights reserved.
//  </copyright>
//  
//  <Create Time>
//    12/03/2012 20:12 
//  </Create Time>
//  
//  <contact owner>
//    liufanping@iveely.com 
//  </contact owner>
//  -----------------------------------------------------------------------------------------------

#region

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using IveelySE.Common;
using IveelySE.Config;

#endregion

namespace IveelySE.IDFS.Store
{
    /// <summary>
    ///   文件片段
    /// </summary>
    [Serializable]
    public class Fragment
    {
        private readonly List<int> List = new List<int>();

        /// <summary>
        ///   片段容量
        /// </summary>
        public int MaxCount = 100;

        /// <summary>
        ///   即将写入文件的数据
        /// </summary>
        private List<PObject> _inFile = new List<PObject>();

        /// <summary>
        ///   构造方法
        ///   （实现在数据结点端，建立片段文件）
        /// </summary>
        public Fragment(string id)
        {
            this.Id = id;
            //  LocalFile.CreateFile(id);
            this.Size = 0;
        }

        //private const int MaxSize = 64 * 1024;// * 1024;
        /// <summary>
        ///   片段最大存放大小
        /// </summary>
        /// <summary>
        ///   文件片段编号
        /// </summary>
        public string Id { get; set; }

        /// <summary>
        ///   文件对应的Hash编码（用于验证）
        /// </summary>
        public int Hash { get; set; }

        /// <summary>
        ///   片段大小
        /// </summary>
        public int Size { get; set; }

        /// <summary>
        ///   创建时间
        /// </summary>
        public DateTime CreateTime { get; set; }

        /// <summary>
        ///   插入数据
        /// </summary>
        /// <param name="data"> 数据字符串数组 </param>
        /// <param name="size"> </param>
        /// <returns> 返回是否插入成功True为插入成功，Flase为插入失败 </returns>
        public bool Add(PObject data, int size)
        {
            //计算数据大小
            this.Size += size;
            //如果当前片段大于64M则不能再添加
            if(this.MaxCount - 1 < this.List.Count)
            {
                //达到饱和，写入文件
                //lock (this)
                //{
                //if (!File.Exists("root\\" + this.Id.ToString()))
                //{
                //    Common.Serialize.Serailzable(inFile, "root\\" + this.Id.ToString());
                //}//{ }
                //}

                if(
                    !Serialize.Serailzable(this._inFile,
                                           Application.GetCrawlerTempDir() +
                                           this.Id.ToString(CultureInfo.InvariantCulture)))
                {
                    List.Add(data.Id);
                    //将数据写入文件中
                    if(this._inFile == null)
                        this._inFile = new List<PObject>();
                    this._inFile.Add(data);
                    return true;
                }

                //清空，减少内存中的无效数据
                this._inFile = null;
                //返回不能添加
                return false;
            }
            //如果当前可以插入
            //将编号写入到集合中
            this.List.Add(data.Id);
            //将数据写入文件中
            this._inFile.Add(data);
            //List<PObject> inFile;
            //if (File.Exists("root\\" + this.Id.ToString()))
            //{
            //    inFile = (List<PObject>)Common.Serialize.UnSerailzable("root\\"+this.Id.ToString());
            //}
            //else
            //{
            //    inFile = new List<PObject>();
            //}
            //if (inFile != null)
            //{
            //    inFile.Add(data);
            //}
            ////如果序列化失败
            //if (!Common.Serialize.Serailzable(inFile, "root\\" + this.Id.ToString()))
            //{
            //    //直到加入为止
            //    Add(data, size);
            //}
            return true;
        }

        /// <summary>
        ///   查找对应的数据
        /// </summary>
        /// <param name="num"> 在片段中的行号 </param>
        /// <returns> 返回该对象 </returns>
        public PObject Find(int num)
        {
            //获取数据编号
            int dataId = this.List[num];

            //List<PObject> inFile = new List<PObject>();
            if(File.Exists(Application.GetCrawlerTempDir() + this.Id.ToString(CultureInfo.InvariantCulture)))
            {
                this._inFile =
                    (List<PObject>)
                    Serialize.UnSerailzable(Application.GetCrawlerTempDir() +
                                            this.Id.ToString(CultureInfo.InvariantCulture));
            }
            foreach(PObject obj in this._inFile)
            {
                if(obj.Id == dataId)
                {
                    return obj;
                }
            }
            return null;
        }

        public static PObject Find(string fragmentId, int dataId)
        {
            var inFile = new List<PObject>();
            if(File.Exists(Application.GetCrawlerTempDir() + fragmentId.ToString(CultureInfo.InvariantCulture)))
            {
                inFile =
                    (List<PObject>)
                    Serialize.UnSerailzable(Application.GetCrawlerTempDir() +
                                            fragmentId.ToString(CultureInfo.InvariantCulture));
            }
            foreach(PObject obj in inFile)
            {
                if(obj.Id == dataId)
                {
                    return obj;
                }
            }
            return null;
        }

        public static PObject FindWhenSearch(string fragmentId, int dataId)
        {
            if(File.Exists(fragmentId.ToString(CultureInfo.InvariantCulture)))
            {
                var inFile =
                    (List<PObject>)
                    Serialize.UnSerailzable(fragmentId.ToString(CultureInfo.InvariantCulture));

                //Need Fix:inFile是一个有序的文件，此处可以使用二分查找来做。

                foreach(PObject obj in inFile)
                {
                    if(obj.Id == dataId)
                    {
                        return obj;
                    }
                }
            }
            return null;
        }
    }
}